// matrix_element_trait.h
#ifndef MATRIX_ELEMENT_TRAIT_H
#define MATRIX_ELEMENT_TRAIT_H

#include <cstdlib>
#include <cmath>


/**
 * A trait keeping information about the element type of a matrix.
 * The meaning of each member is described below
 */
template<typename T>
struct MatrixElementTrait
{
    enum 
    {
        // Indication of whether or not invertion is a allowed for a matrix with the given element type
        IsInvertable = false
    };
    // If value v of type T obeys: Abs(v) < Precision, v is considered to be 'zero'
    static T const Precision = 0;
    // Absolute/numeric value
    static T Abs(T val) { return std::abs(val); }
    // Get a random element value
    static T GetRandom() { return std::rand(); }
};

template<>
struct MatrixElementTrait<double>
{
    enum 
    {
        IsInvertable = true
    };
    static double const Precision;
    static double Abs(double val) { return std::fabs(val); }
    static double GetRandom() { return std::rand() / (RAND_MAX + 1.0) - 0.5; }
};

template<>
struct MatrixElementTrait<float>
{
    enum 
    {
        IsInvertable = true
    };
    static float const Precision;
    static float Abs(float val) { return std::fabs(val); }
    static float GetRandom() { return rand() / (RAND_MAX + 1.0); }
};

#endif // MATRIX_ELEMENT_TRAIT_H
